﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Drawing;
using System.Windows.Media.Imaging;
using PromoServer.Library.Communication;
using PromoServer.Library.Data;
using PromoServer.Library.Entities;
using EnterpriseDT.Net.Ftp;

namespace PromoServer.Library
{
    public class PromoSocketServer
    {
        public event UpdateClientStatusEventHandler ClientStatusUpdate;

        public event SocketConnectingEventHandler DeviceConnecting;

        public event FoundNewDeviceEventHandler NewDeviceFound;

        public event RegisteredNewDeviceEventHandler DeviceRegistered;

        public event DeviceResolutionChangedEventHandler DeviceResolutionChanged;

        private AsyncSocket socketServer;

        private AsyncSocket socketClient;

        private PSData psData;

        private UInt16 socketClientPort;

        private FTPConnection ftpConnection;

        public PromoSocketServer()
        {
            // Set ports
            UInt16 port;
            port = Convert.ToUInt16(PromoServer.Library.Properties.Settings.Default.Promo_Server_Port);

            socketClientPort = Convert.ToUInt16(PromoServer.Library.Properties.Settings.Default.Promo_Client_Port);

            // Listening socket
            socketServer = new AsyncSocket();

            // Tell AsyncSocket to invoke its delegate methods on our form thread
            // Note: Accepted sockets will automatically inherit this setting as well
            socketServer.SynchronizingObject = null;
            socketServer.AllowMultithreadedCallbacks = true;

            // Register for the events we're interested in
            socketServer.DidAccept += new AsyncSocket.SocketDidAccept(ConnectionAccepted);

            // Initialize PS Data object
            psData = new PSData();

            // Listen for connections
            Exception error;
            if (!socketServer.Accept(port, out error))
            {
                //LogError("Error starting server: {0}", error);
                return;
            }

        }

        public PromoSocketServer(Int16 Port)
        {
            // Set ports
            UInt16 port;
            port = Convert.ToUInt16(Port);

            socketClientPort = Convert.ToUInt16(PromoServer.Library.Properties.Settings.Default.Promo_Client_Port);

            // Listening socket
            socketServer = new AsyncSocket();

            // Tell AsyncSocket to invoke its delegate methods on our form thread
            // Note: Accepted sockets will automatically inherit this setting as well
            socketServer.SynchronizingObject = null;
            socketServer.AllowMultithreadedCallbacks = true;

            // Register for the events we're interested in
            socketServer.DidAccept += new AsyncSocket.SocketDidAccept(ConnectionAccepted);

            // Initialize PS Data object
            psData = new PSData();

            // Listen for connections
            Exception error;
            if (!socketServer.Accept(port, out error))
            {
                //LogError("Error starting server: {0}", error);
                return;
            }
        }

        #region SOCKET_FUNCTIONS

        private void ConnectionAccepted(AsyncSocket sender, AsyncSocket newSocket)
        {
            // Register for event to determine if the socket closed
            newSocket.DidRead += new AsyncSocket.SocketDidRead(ConnectionRead);
            newSocket.DidWrite += new AsyncSocket.SocketDidWrite(ConnectionWrite);
            newSocket.WillClose += new AsyncSocket.SocketWillClose(ConnectionClosing);
            newSocket.DidClose += new AsyncSocket.SocketDidClose(ConnectionClosed);

            // Write confirmation to client
            byte[] data = Encoding.UTF8.GetBytes("ok");
            newSocket.Write(data, -1, 0);

            // Fire new socket client event and pass new socket object
            //DeviceConnecting(sender, newSocket);
        }

        private void ConnectionWrite(AsyncSocket sender, long tag)
        {
            sender.Read(AsyncSocket.CRLFData, -1, 0);
        }

        private void ConnectionRead(AsyncSocket sender, byte[] data, long tag)
        {
            String message = null;
            XmlDocument xmlMessage = new XmlDocument();
            try
            {
                // Load message to xml document
                message = Encoding.UTF8.GetString(data);
                xmlMessage.LoadXml(message.ToLower());

                // Get instruction
                string instruction = GetInstruction(xmlMessage);

                // Process instruction
                if (instruction == "register")
                {
                    // Attempt to register device
                    RegisterDevice(sender.RemoteAddress.ToString(), GetContent(xmlMessage), GetDisplayWidth(xmlMessage), GetDisplayHeight(xmlMessage));

                    // Send success back to client
                    byte[] successData = Encoding.UTF8.GetBytes("success");
                    sender.Write(successData, -1, 0);
                }
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("ConnectionRead", ex.Message, true);
            }
        }

        private void ConnectionClosing(AsyncSocket sender, Exception ex)
        {
            //ClientStatusUpdate(sender.RemoteAddress.ToString(), "DISCONNECTED");
            //ClientStatusUpdate("192.168.1.124", "DISCONNECTED");
        }

        private void ConnectionClosed(AsyncSocket sender)
        {
            //connectedSockets.Remove(sender);
        }

        #endregion

        #region MESSAGE_FUNCTIONS

        private string GetInstruction(XmlDocument xmlMessage)
        {
            string instruction = "";
            XmlNodeList xmlInstructionNode = xmlMessage.GetElementsByTagName("instruction");
            instruction = xmlInstructionNode[0].InnerText;
            return instruction;
        }

        private string GetContent(XmlDocument xmlMessage)
        {
            string content = string.Empty;
            XmlNodeList xmlInstructionNode = xmlMessage.GetElementsByTagName("content");
            content = xmlInstructionNode[0].InnerText;
            return content;
        }

        private int GetDisplayWidth(XmlDocument xmlMessage)
        {
            string displayWidth = string.Empty;
            XmlNodeList xmlInstructionNode = xmlMessage.GetElementsByTagName("resolution");
            displayWidth = xmlInstructionNode[0].Attributes["width"].Value.ToString();
            return Convert.ToInt32(displayWidth);
        }

        private int GetDisplayHeight(XmlDocument xmlMessage)
        {
            string displayHeight = string.Empty;
            XmlNodeList xmlInstructionNode = xmlMessage.GetElementsByTagName("resolution");
            displayHeight = xmlInstructionNode[0].Attributes["height"].Value.ToString();
            return Convert.ToInt32(displayHeight);
        }

        private bool SendInstruction(Device device, XmlDocument xmlMessage)
        {
            Exception socketErr;
            socketClient = new AsyncSocket();
            try
            {
                if (!socketClient.Connect(device.HostName, socketClientPort, out socketErr))
                {
                    // Log error if socket connection fails
                    PromoLog promoLog = new PromoLog();
                    promoLog.Log("PromoServer.SendInstruction", socketErr.Message, true);

                    // Exit
                    return false;
                }

                // Send message to client
                byte[] xmlData = Encoding.UTF8.GetBytes(xmlMessage.OuterXml);
                socketClient.Write(xmlData, -1, 0);
                if (socketClient.Connected)
                {
                    socketClient.CloseAfterWriting();
                }

                return true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.SendInstruction", ex.Message, true);
                return false;
            }
        }

        public bool IdentifyClient(Device device)
        {
            try
            {
                // Declare xml message
                XmlDocument xmlMessage = new XmlDocument();

                // Create xml declaration
                XmlDeclaration xmlDecl = xmlMessage.CreateXmlDeclaration("1.0", "utf-8", null);
                xmlMessage.AppendChild(xmlDecl);

                // Create root node (message)
                XmlElement messageRoot = xmlMessage.CreateElement("message");
                xmlMessage.AppendChild(messageRoot);

                // Create host name node
                XmlElement messageInstruction = xmlMessage.CreateElement("instruction");
                messageInstruction.InnerText = "identify";
                messageRoot.AppendChild(messageInstruction);

                XmlElement messageDisplayName = xmlMessage.CreateElement("display_name");
                messageDisplayName.InnerText = device.DisplayName;
                messageRoot.AppendChild(messageDisplayName);

                if (!SendInstruction(device, xmlMessage))
                {
                    // Send failed
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.IdentifyClient", ex.Message, true);
                return false;
            }
        }

        public bool DisplayDefaultLayout(Device device)
        {
            try
            {
                // Declare xml message
                XmlDocument xmlMessage = new XmlDocument();

                // Create xml declaration
                XmlDeclaration xmlDecl = xmlMessage.CreateXmlDeclaration("1.0", "utf-8", null);
                xmlMessage.AppendChild(xmlDecl);

                // Create root node (message)
                XmlElement messageRoot = xmlMessage.CreateElement("message");
                xmlMessage.AppendChild(messageRoot);

                // Create host name node
                XmlElement messageInstruction = xmlMessage.CreateElement("instruction");
                messageInstruction.InnerText = "display_default";
                messageRoot.AppendChild(messageInstruction);

                if (!SendInstruction(device, xmlMessage))
                {
                    // Send failed
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.DisplayDefaultLayout", ex.Message, true);
                return false;
            }
        }

        public bool DisplayCustomLayout(Device device)
        {
            try
            {
                // Declare xml message
                XmlDocument xmlMessage = new XmlDocument();

                // Create xml declaration
                XmlDeclaration xmlDecl = xmlMessage.CreateXmlDeclaration("1.0", "utf-8", null);
                xmlMessage.AppendChild(xmlDecl);

                // Create root node (message)
                XmlElement messageRoot = xmlMessage.CreateElement("message");
                xmlMessage.AppendChild(messageRoot);

                // Create host name node
                XmlElement messageInstruction = xmlMessage.CreateElement("instruction");
                messageInstruction.InnerText = "display_custom";
                messageRoot.AppendChild(messageInstruction);

                if (!SendInstruction(device, xmlMessage))
                {
                    // Send failed
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.DisplayCustomLayout", ex.Message, true);
                return false;
            }
        }

        private bool SendDefaultLayout(Device device)
        {
            bool wasSuccess = false;
            try
            {
                //// Load default layout
                //List<LayoutContent> defaultLayout;
                //defaultLayout = psData.GetDefaultLayoutsByDeviceID(device.DeviceID);
                
                //// Generate XML message
                //// Declare xml message
                //XmlDocument xmlMessage = new XmlDocument();

                //// Create xml declaration
                //XmlDeclaration xmlDecl = xmlMessage.CreateXmlDeclaration("1.0", "utf-8", null);
                //xmlMessage.AppendChild(xmlDecl);

                //// Create root node (message)
                //XmlElement messageRoot = xmlMessage.CreateElement("message");
                //xmlMessage.AppendChild(messageRoot);

                //// Create instruction node
                //XmlElement messageInstruction = xmlMessage.CreateElement("instruction");
                //messageInstruction.InnerText = "default_display";
                //messageRoot.AppendChild(messageInstruction);

                //// Append content nodes
                //XmlElement messageContent;
                //foreach (LayoutContent layout in defaultLayout)
                //{
                //    messageContent = xmlMessage.CreateElement("content");
                //    messageContent.SetAttribute("orientation", layout.Orientation);
                //    messageContent.SetAttribute("sequence", layout.Sequence.ToString());
                //    messageContent.SetAttribute("duration", layout.Duration.ToString());
                //    messageContent.SetAttribute("image", Path.GetFileName(layout.ContentFileName));
                //    messageRoot.AppendChild(messageContent);
                //}
                
                //if (!SendInstruction(device, xmlMessage))
                //    wasSuccess = false;
                //else
                //    wasSuccess = true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.SendDefaultLayout", ex.Message, true);

                wasSuccess = false;
            }
            return wasSuccess;
        }

        private bool SendCustomLayout(Device device)
        {
            bool wasSuccess = false;
            try
            {
                //// Load default layout
                //List<LayoutContent> defaultLayout;
                //defaultLayout = psData.GetCustomLayoutsByDeviceID(device.DeviceID);

                //// Generate XML message
                //// Declare xml message
                //XmlDocument xmlMessage = new XmlDocument();

                //// Create xml declaration
                //XmlDeclaration xmlDecl = xmlMessage.CreateXmlDeclaration("1.0", "utf-8", null);
                //xmlMessage.AppendChild(xmlDecl);

                //// Create root node (message)
                //XmlElement messageRoot = xmlMessage.CreateElement("message");
                //xmlMessage.AppendChild(messageRoot);

                //// Create instruction node
                //XmlElement messageInstruction = xmlMessage.CreateElement("instruction");
                //messageInstruction.InnerText = "custom_display";
                //messageRoot.AppendChild(messageInstruction);

                //// Append content nodes
                //XmlElement messageContent;
                //foreach (LayoutContent layout in defaultLayout)
                //{
                //    messageContent = xmlMessage.CreateElement("content");
                //    messageContent.SetAttribute("sequence", layout.Sequence.ToString());
                //    messageContent.SetAttribute("duration", layout.Duration.ToString());
                //    messageContent.SetAttribute("image", Path.GetFileName(layout.ContentFileName));
                //    messageRoot.AppendChild(messageContent);
                //}

                //if (!SendInstruction(device, xmlMessage))
                //    wasSuccess = false;
                //else
                //    wasSuccess = true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.SendCustomLayout", ex.Message, true);

                wasSuccess = false;
            }
            return wasSuccess;
        }

        #endregion

        #region REGISTRATION_FUNCTIONS

        private bool CreateDeviceDirectories(string deviceHostName)
        {
            bool wasSuccess = false;
            try
            {
                // Get application path
                string path;
                path = System.IO.Path.GetDirectoryName(
                   System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

                // Create main device directory
                string rootDeviceDirectory = path + @"\devices\" + deviceHostName;

                // Use URI path
                string uriRootDeviceDir = rootDeviceDirectory;
                rootDeviceDirectory = new Uri(uriRootDeviceDir).LocalPath;

                if (Directory.Exists(rootDeviceDirectory))
                    Directory.Delete(rootDeviceDirectory, true);

                Directory.CreateDirectory(rootDeviceDirectory);

                // Create sub directories
                string defDir = rootDeviceDirectory + @"\" + "default";
                Directory.CreateDirectory(defDir);

                string custDir = rootDeviceDirectory + @"\" + "custom";
                Directory.CreateDirectory(custDir);

                // Create layout configuration files
                XmlDocument layoutConfig = new XmlDocument();
                XmlNode layoutDeclarationNode = layoutConfig.CreateXmlDeclaration("1.0", "utf-8", null);
                layoutConfig.AppendChild(layoutDeclarationNode);

                XmlNode rootNode = layoutConfig.CreateElement("content");
                layoutConfig.AppendChild(rootNode);

                layoutConfig.Save(defDir + @"\" + "layout.xml");
                layoutConfig.Save(custDir + @"\" + "layout.xml");

                wasSuccess = true;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("CreateDeviceDirectories", ex.Message, true);
                wasSuccess = false;
            }

            // Log success
            PromoLog promoLogSuccess = new PromoLog();
            promoLogSuccess.Log("CreateDeviceDirectories", "Device directories created successfully during registration", false);

            return wasSuccess;
        }

        private void RegisterDevice(string deviceHostName, string displayLayout, int displayWidth, int displayHeight)
        {
            // Verify device does not exist and validate resolution if it does exist
            if (DoesDeviceExist(deviceHostName))
            {
                // If resoultion changed, update resolution
                bool sameResolution = ValidateDeviceResolution(deviceHostName, displayWidth, displayHeight);

                // Fire resolution changed event
                if (!sameResolution)
                    DeviceResolutionChanged(deviceHostName);

                // Exit
                return;
            }

            // Create device directories - DEPRACATED DUE TO DATABASE REGISTRATION
            //if (!CreateDeviceDirectories(deviceHostName))
            //    return;

            // Add device to config db
            if (AddRegisteredDevice(deviceHostName, displayLayout, displayWidth, displayHeight))
            {
                // Fire DeviceFound event
                try
                {
                    NewDeviceFound(deviceHostName);
                }
                catch
                { 
                    // Resume
                }

                // Fire DeviceRegistered event
                Device newDevice = psData.GetNewestDevice();
                try
                {
                    DeviceRegistered(newDevice);
                }
                catch
                {
                    // Resume
                }
                
                // Log success
                PromoLog promoLog = new PromoLog();
                promoLog.Log("RegisterDevice", "Successfully registered device (" + deviceHostName + ")", false); 
            }
        }

        private bool AddRegisteredDevice(string hostName, string displayLayout, int displayWidth, int displayHeight)
        {
            try
            {
                // Add device to database
                psData.AddDevice(hostName, hostName, displayLayout, displayWidth, displayHeight);
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("AddRegisteredDevice", "Failed to register device (" + hostName + ")", true);
                return false;
            }
            return true;
        }

        #endregion

        #region HELPER_FUNCTIONS

        private bool DoesDeviceExist(string deviceHostName)
        {
            bool deviceExists = false;

            // Load list of registered devices
            List<string> registeredDevices = new List<string>();
            registeredDevices = GetCurrentlyRegisteredDevices();

            foreach (string device in registeredDevices)
            {
                if (device == deviceHostName)
                    deviceExists = true;
            }

            return deviceExists;
        }

        private List<string> GetCurrentlyRegisteredDevices()
        {
            List<string> currentDevices = new List<string>();

            try
            {
                // Get list of devices
                List<Device> lstDevices = new List<Device>();
                lstDevices = psData.GetDevices();

                // Add each device to list
                foreach (Device device in lstDevices)
                {
                    currentDevices.Add(device.HostName);
                }
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.GetCurrentlyRegisteredDevices", ex.Message, true);
            }
            
            return currentDevices;
        }

        private bool ValidateDeviceResolution(string hostName, int deviceWidth, int deviceHeight)
        {
            int deviceID = psData.GetDeviceIDByHostName(hostName);
            int currentWidth = psData.GetDeviceWidth(deviceID);
            int currentHeight = psData.GetDeviceHeight(deviceID);

            // Return true if resolution has not changed, else update and return false
            if (currentWidth != deviceWidth || currentHeight != deviceHeight)
            {
                psData.UpdateDeviceResolution(deviceID, deviceWidth, deviceHeight);
                return false;
            }
            else
                return true;
        }

        private bool doesImageRequireScale(Device device, LayoutContent layout)
        {
            try
            {
                if (layout.ContentFileName == string.Empty)
                    return false;

                bool scaleRequired = false;

                // Get device aspect ratio
                int deviceWidth = psData.GetDeviceWidth(device.DeviceID);
                int deviceHeight = psData.GetDeviceHeight(device.DeviceID);
                double deviceRatio = Math.Round(Convert.ToDouble(deviceWidth) / Convert.ToDouble(deviceHeight), 1);

                // Get layout image aspect ratio
                BitmapImage bmpImg = new BitmapImage(new Uri(layout.ContentFileName));
                double layoutWidth = bmpImg.Width;
                double layoutHeight = bmpImg.Height;
                double layoutRatio = Math.Round(layoutWidth / layoutHeight, 1);

                double ratioDiff = Math.Round(layoutRatio - deviceRatio, 1);

                // If aspect ratio is same, width/height differ & ShowImageFullSceen = true, then return true (scale image)
                if (ratioDiff <= .1 && Convert.ToDouble(deviceWidth) != layoutWidth && layout.Stretch == true)
                    scaleRequired = true;
                else
                    scaleRequired = false;

                return scaleRequired;
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.doesImageRequireScale", ex.Message, true);
                return false;
            }
        }

        private string scaleImage(string imageFilePath, int newWidth)
        {
            BitmapImage myBitmapImage = new BitmapImage();

            // BitmapSource objects like BitmapImage can only have their properties 
            // changed within a BeginInit/EndInit block.
            myBitmapImage.BeginInit();
            myBitmapImage.UriSource = new Uri(imageFilePath);

            // To save significant application memory, set the DecodePixelWidth or   
            // DecodePixelHeight of the BitmapImage value of the image source to the desired  
            // height or width of the rendered image. If you don't do this, the application will  
            // cache the image as though it were rendered as its normal size rather then just  
            // the size that is displayed. 
            // Note: In order to preserve aspect ratio, set DecodePixelWidth 
            // or DecodePixelHeight but not both.
            myBitmapImage.DecodePixelWidth = newWidth;
            myBitmapImage.EndInit();

            // Create Bitmap from BitMapImage
            Bitmap bmp = BitmapImage2Bitmap(myBitmapImage);

            // Create temporary file name
            FileInfo fi = new FileInfo(imageFilePath);
            string newFilePath = string.Empty;

            newFilePath = System.AppDomain.CurrentDomain.BaseDirectory;
            newFilePath += Properties.Settings.Default.Images_Directory;

            string newFileName = "tmp_" + Guid.NewGuid().ToString() + fi.Extension.ToLower();
            newFilePath += newFileName;

            // Save scaled image to temporary file
            if (fi.Extension.ToLower() == ".jpg" || fi.Extension.ToLower() == ".jpeg")
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            else if (fi.Extension.ToLower() == ".png")
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Png);
            else if (fi.Extension.ToLower() == ".bmp")
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Bmp);
            else if (fi.Extension.ToLower() == ".gif")
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Gif);
            else if (fi.Extension.ToLower() == ".tif" || fi.Extension.ToLower() == ".tiff")
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Tiff);
            else
                bmp.Save(newFilePath, System.Drawing.Imaging.ImageFormat.Jpeg);

            // Return temporary file path
            return newFilePath;
        }

        private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
        {
            using (MemoryStream outStream = new MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create(bitmapImage));
                enc.Save(outStream);
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

                // return bitmap; <-- leads to problems, stream is closed/closing ...
                return new Bitmap(bitmap);
            }
        }

        #endregion

        #region FTP_FUNCTIONS

        public bool SendDefaultContent(Device device)
        {
            bool wasSuccess = false;
            try
            {
                //List<LayoutContent> defaultLayout;
                //defaultLayout = psData.GetDefaultLayoutsByDeviceID(device.DeviceID);

                //// Set FTP connection properties
                //ftpConnection = new FTPConnection();
                //ftpConnection.TransferType = FTPTransferType.BINARY;

                //ftpConnection.ServerAddress = device.HostName;
                //ftpConnection.ServerPort = 21;
                //ftpConnection.UserName = "pi";
                //ftpConnection.Password = "raspberry";

                //// Upload image files
                //string fileName = string.Empty;
                //foreach (LayoutContent layout in defaultLayout)
                //{
                //    // Check if image requires scaling
                //    bool isScaleRequired = doesImageRequireScale(device, layout);

                //    // Get image file to upload
                //    string uploadImageFilePath = string.Empty;
                //    if (isScaleRequired)
                //    {
                //        // If image requires scaling, get new image file path
                //        uploadImageFilePath = scaleImage(layout.ContentFileName, psData.GetDeviceWidth(device.DeviceID));
                //    }
                //    else
                //    {
                //        // If image was not scaled, get original layout image file path
                //        uploadImageFilePath = layout.ContentFileName;
                //    }

                //    fileName = Path.GetFileName(layout.ContentFileName);

                //    // Upload file
                //    if (!ftpConnection.IsConnected)
                //    {
                //        ftpConnection.Connect();
                //        ftpConnection.ChangeWorkingDirectory("default");
                //    }

                //    ftpConnection.UploadFile(uploadImageFilePath, fileName);

                //    // If image was scaled, delete temporary scaled image
                //    if (isScaleRequired)
                //    {
                //        if (File.Exists(uploadImageFilePath))
                //            File.Delete(uploadImageFilePath);
                //    }
                //}

                wasSuccess = SendDefaultLayout(device);
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.SendDefaultContent", ex.Message, true);

                wasSuccess = false;
            }
            finally
            {
                // Close FTP connection
                if (ftpConnection.IsConnected)
                    ftpConnection.Close();

                ftpConnection.Dispose();
                ftpConnection = null;
            }
            return wasSuccess;
        }

        public bool SendCustomContent(Device device)
        {
            bool wasSuccess = false;
            try
            {
                //List<LayoutContent> defaultLayout;
                //defaultLayout = psData.GetCustomLayoutsByDeviceID(device.DeviceID);

                //// Set FTP connection properties
                //ftpConnection = new FTPConnection();
                //ftpConnection.TransferType = FTPTransferType.BINARY;

                //ftpConnection.ServerAddress = device.HostName;
                //ftpConnection.ServerPort = 21;
                //ftpConnection.UserName = "pi";
                //ftpConnection.Password = "raspberry";

                //// Upload image files
                //string fileName = string.Empty;
                //foreach (LayoutContent layout in defaultLayout)
                //{
                //    // Check if image requires scale
                //    bool isScaleRequired = doesImageRequireScale(device, layout);

                //    // Get image file to upload
                //    string uploadImageFilePath = string.Empty;
                //    if (isScaleRequired)
                //    {
                //        // If image requires scaling, get new image file path
                //        uploadImageFilePath = scaleImage(layout.ContentFileName, psData.GetDeviceWidth(device.DeviceID));
                //    }
                //    else
                //    {
                //        // If image was not scaled, get original layout image file path
                //        uploadImageFilePath = layout.ContentFileName;
                //    }

                //    fileName = Path.GetFileName(layout.ContentFileName);

                //    // Upload file
                //    if (!ftpConnection.IsConnected)
                //    {
                //        ftpConnection.Connect();
                //        ftpConnection.ChangeWorkingDirectory("custom");
                //    }

                //    ftpConnection.UploadFile(uploadImageFilePath, fileName);

                //    // If image was scaled, delete temporary scaled image
                //    if (isScaleRequired)
                //    {
                //        if (File.Exists(uploadImageFilePath))
                //            File.Delete(uploadImageFilePath);
                //    }
                //}

                wasSuccess = SendCustomLayout(device);
            }
            catch (Exception ex)
            {
                // Log error
                PromoLog promoLog = new PromoLog();
                promoLog.Log("PromoServer.SendCustomContent", ex.Message, true);

                wasSuccess = false;
            }
            finally
            {
                // Close FTP connection
                if (ftpConnection.IsConnected)
                    ftpConnection.Close();

                ftpConnection.Dispose();
                ftpConnection = null;
            }
            return wasSuccess;
        }

        #endregion

    }
}
